#include"Detection.h"
#include<fstream>
using namespace std;

//using namespace System;
//using namespace System::Collections;


int currentID;
int maxRange;
void AddUnique(vector<int> &v,int t)
{
	if(t>=maxRange || t<0)
	{
		char s[]={"catch me"};
	}

	for(int i=0;i<v.size();i++)
	{
		if(v[i]==t)
		{
			return;
		}

	}
	v.push_back(t);
}
vector<int> CheckNeighbors(int** compMat,int PointX,int PointY,int NextComp)
{
	maxRange=NextComp;
	
	for(int i=0;i<322;i++)
	{
		for(int j=0;j<242;j++)
		{
			if(compMat[i][j]>=NextComp || compMat[i][j]<0)
			{
				char s[]={":S:S"}; 
			}

		}
	}
		
	vector<int> result;
	int value;
	value=compMat[PointX+1][PointY] ;
	if(value>=maxRange || value<0)
	{
		char s[]={"catch me"};
	}
	if( value > 0 )
	{
		AddUnique(result,value);
	}
	value=compMat[PointX-1][PointY];
	if(value>=maxRange || value<0)
	{
		char s[]={"catch me"};
	}
	if(value > 0)
	{
		AddUnique(result,value);
	}
	value= compMat[PointX+1][PointY+1];
	if(value>=maxRange || value<0)
	{
		char s[]={"catch me"};
	}
	if(value > 0)
	{
		AddUnique(result,value);
	}
	value= compMat[PointX+1][PointY-1];
	if(value>=maxRange || value<0)
	{
		char s[]={"catch me"};
	}
	if(value > 0)
	{
		AddUnique(result,value);
	}
	if(value>=maxRange || value<0)
	{
		char s[]={"catch me"};
	}
	value=compMat[PointX][PointY-1];
	if(value>=maxRange || value<0)
	{
		char s[]={"catch me"};
	}
	if(value > 0)
	{
		AddUnique(result,value);
	}
	if(value>=maxRange || value<0)
	{
		char s[]={"catch me"};
	}
	value=compMat[PointX][PointY+1];
	if(value > 0)
	{
		AddUnique(result,value);
	}
	if(value>=maxRange || value<0)
	{
		char s[]={"catch me"};
	}
	value= compMat[PointX-1][PointY-1];
	if(value > 0)
	{
		AddUnique(result,value);
	}
	if(value>=maxRange || value<0)
	{
		char s[]={"catch me"};
	}
	value= compMat[PointX-1][PointY+1];
	if(value > 0)
	{
		AddUnique(result,value);
	}
	
	for(int i=0;i<result.size();i++)
	{
		if(result[i]>NextComp || result[i]<0)
		{
			char s[]={"Error"};
		}
	}
	return result;
}



Detection::Detection(IplImage* frame)
{
	if(frame==NULL ) 
	{
		puts("unable to load the frame");exit(0);
	}
	//printf("frame loaded");
	//cvNamedWindow("original",CV_WINDOW_AUTOSIZE);
	//cvNamedWindow("Result",CV_WINDOW_AUTOSIZE);
	//IplImage* hsv;
	//cvCvtColor( frame, hsv, CV_BGR2HSV );
	height = frame->height;
	width = frame->width;
	step =frame->widthStep;
	channels = frame->nChannels;
	data = (uchar *)frame->imageData;
	result=cvCreateImage( cvGetSize(frame), 8, 1 );
	stepr=result->widthStep;
	channelsr=result->nChannels;
	datar = (uchar *)result->imageData;
	Num=1;

}
void Detection::DetectRed()
{

	for(int i=0;i < (height);i++) 
	{
		for(int j=0;j <(width);j++)
			if((data[i*step+j*channels]<80)&&(data[i*step+j*channels+1]<80)&&(data[i*step+j*channels+2]>140)
				&&(data[i*step+j*channels+2]<=255))
			{
				datar[i*stepr+j*channelsr]=255;
				Points.push_back(cvPoint(i,j));
			}
			else
			{
				datar[i*stepr+j*channelsr]=0;
			}
			//RedPoint=GetCenter(Points);
	}


}

void Detection::DetectGreen()
{

	for(int i=0;i < (height);i++) 
		for(int j=0;j <(width);j++)
		{
			if((data[i*step+j*channels+2]<100)&&(data[i*step+j*channels]<100)&&(data[i*step+j*channels+1]>100)
				&&(data[i*step+j*channels+1]<255))
			{
				Points.push_back(cvPoint(i,j));
				datar[i*stepr+j*channelsr]=255;
			}

		}
		//GreenPoint=GetCenter(Points);

		//datar[i*stepr+j*channelsr]=0;
}
void Detection::DetectBlue()
{
}

CvPoint* Detection::GetCenter(vector<CvPoint> Point)
{
	CvPoint* Center=new CvPoint();
	for(int i=0;i<Point.size();i++)
	{ 
		Center->x=Center->x+Point[i].x;
		Center->y=Center->y+Point[i].y;
	}
	Center->x=((Center->x)/Point.size());
	Center->y=((Center->y)/Point.size());
	return Center;

}
CvPoint* Detection::RedPosition()
{
	return RedPoint;
}
CvPoint* Detection::GreenPosition()
{
	return GreenPoint;
}
IplImage* Detection::GetResult()
{
	return result;
}
void Detection::DetectHead()
{
}

CvPoint* Detection::Segmentation(IplImage* img)
{

	/*int L=0;
	bool flag=false;
	data = (uchar *)img->imageData;
	step=img->widthStep;
	channels=img->nChannels;*/
	//vector<CvPoint>Seg1;
	int matLength=img->height+2;
	int matWidth=img->width+2;
	int** compMat = new int*[matWidth];
	int c=0;
	for(c=0;c<matWidth;c++)
	{
		compMat[c]=new int[matLength];
		for(int i=0;i<matLength;i++)
		{
			compMat[c][i]=0;
		}
	}




	//{	
	//	CvPoint temp;//-1
	//	for(int i=0;i<(Points.size()-1);i++)
	//	{
	//		for(int j=i;j<Points.size()-1;j++)
	//		{
	//			if(Points[j].x > Points[j+1].x)
	//			{
	//				temp=Points[j];
	//				Points[j]=Points[j+1];
	//				Points[j+1]=temp;
	//			}

	//		}
	//	}
	//}


	////sort on Y

	//{
	//	vector<int> offsets;
	//	offsets.push_back(0);
	//	{
	//		for(int i=1;i<Points.size();i++)
	//		{
	//			if(Points[i].x> Points[i-1].x)
	//			{
	//				offsets.push_back(i);
	//			}
	//		}
	//	}
	//	offsets.push_back(Points.size()-1);
	//	for(int i=0;i<offsets.size()-1;i++)
	//	{
	//		int start=offsets[i];
	//		int end=offsets[i+1];
	//		CvPoint temp;
	//		for(int j=start;j<end-1;j++)
	//		{
	//			for(int k=j;k<end-1;k++)
	//			{
	//				if(Points[k].y>Points[k+1].y)
	//				{
	//					temp=Points[k];
	//					Points[k]=Points[k+1];
	//					Points[k+1]=temp;

	//				}
	//			}
	//		}

	//	}
	//}

	int NextComp=1;
	CvPoint current;
	int	pointX=0;
	int	pointY=0;
	vector<int> neighbors;
	vector<int> map;
	map.push_back(0);
	int sampler=0;
	for(int v=0;v<Points.size();v++)
	{
		currentID=v;
		
			for(int i=0;i<matWidth;i++)
				for(int j=0;j<matLength;j++)
				{
					if(compMat[i][j]>=NextComp || compMat[i][j]<0)
					{
						char s[]={":S:S"}; 
					}

				}
		current=Points[v];
		pointX=current.y+1;
		pointY=current.x+1;
		neighbors= CheckNeighbors(compMat,pointX,pointY,NextComp);
		int neighborCount=neighbors.size();
		if(neighborCount==0)
		{
			compMat[pointX][pointY]=NextComp;
			map.push_back(NextComp);
			++NextComp;
		}
		else if(neighborCount==1)
		{
			compMat[pointX][pointY]=neighbors[0];
		}
		else
		{
			int minIndex=neighbors[0];
			if(minIndex>=map.size() || minIndex<0)
			{
			ofstream x("points.txt");
			{
				for(int i=0;i<Points.size();i++)
				{
					x<<Points[i].x<<" "<<Points[i].y<<endl; 
				}
			}
			x.close();

			}
			int min=map[minIndex];
			int i=1;
			for(;i<neighborCount;i++)
			{
				int oof=neighbors[i];
				int bom=map.size()-1;
				if(map[neighbors[i]]<min)
				{
					minIndex=neighbors[i];
					min=map[minIndex];
				}
			}
			compMat[pointX][pointY]=minIndex;
			for(i=0;i<neighborCount;i++)
			{
				map[neighbors[i]]=min;
			}
		}
		
		if(compMat[pointX][pointY]> NextComp || compMat[pointX][pointY]<0)
		{
			char a[]={"Help"};
		}
	}
	int currentValue=0;
	for(int j=1;j<map.size();j++)
	{
		if(map[j]==currentValue)
		{
			map[j]=map[j-1];
		}
		else
		{
			currentValue=map[j];
			map[j]=map[j-1]+1;
		}
	}
	//	ofstream x("out.txt");
	//CvPoint* Center=new CvPoint[3];
	//int N1=0,N2=0,N3=0;
	//for(int i=0;i<3;i++)
	//{
	//	Center[i].x=0;
	//	Center[i].y=0;
	//}

	//for(int k=0;k<matWidth;k++)
	//{
	//	for(int l=0;l<matLength;l++)
	//	{
	//		//	x<<map[compMat[k][l]];
	//		if(map[compMat[k][l]]==1)
	//		{
	//			N1++;
	//			Center[0].x=Center[0].x+l;
	//			Center[0].y=Center[0].y+k;
	//		}
	//		else if(map[compMat[k][l]]==2)
	//		{N2++;
	//		Center[1].x=Center[1].x+l;
	//		Center[1].y=Center[1].y+k;
	//		}
	//		else if(map[compMat[k][l]]==3)
	//		{N3++;
	//		Center[2].x=Center[2].x+l;
	//		Center[2].y=Center[2].y+k;
	//		}
	//	}

	//	//	x<<endl;
	//}
	//if(N1!=0)
	//{
	//	Center[0].x=Center[0].x/N1;
	//	Center[0].y=Center[0].y/N1;
	//}
	//if(N2!=0)
	//{
	//	Center[1].x=Center[1].x/N2;
	//	Center[1].y=Center[1].y/N2;
	//}
	//if(N3!=0)
	//{
	//	Center[2].x=Center[2].x/N3;
	//	Center[2].y=Center[2].y/N3;
	//}

	{
		for(int i=0;i<matWidth;i++)
		{
			delete[] compMat[i];
		}
		delete[] compMat;

	}
	//x.close();


	//
	//Seg1.push_back(cvPoint(Points[0].x,Points[0].y));
	////Points.erase(Points.begin());
	//for (int z=1; z< Points.size(); z++)
	//{        
	//		//if( (data[ ((Points[z].x)+1) *step+(Points[z].y)*channels+2]==255)||(data[ (Points[z].x) *step+((Points[z].y)-1)*channels+2]==255)
	//  //           ||(data[ ((Points[z].x)-1) *step+(Points[z].y)*channels+2]==255)||(data[ (Points[z].x) *step+((Points[z].y)+1)*channels+2]==255) 
	//  //            ||(data[ ((Points[z].x)-1) *step+((Points[z].y)-1)*channels+2]==255)||(data[ ((Points[z].x)+1) *step+((Points[z].y)+1)*channels+2]==255) 
	//		//   ||(data[ ((Points[z].x)+1) *step+((Points[z].y)-1)*channels+2]==255)||(data[ ((Points[z].x)-1) *step+((Points[z].y)+1)*channels+2]==255))
	//		//{
	//		//	int Size=Seg1.size();
	//	 //  //   for(int i=Size-1;i>=0;i--)
	//		//  //{  
	//		//	 // if( (((Points[z].x)+1)==Seg1[i].x&&Points[z].y==Seg1[i].y)
	//		//		//  ||(((Points[z].x)+1)==Seg1[i].x&&((Points[z].y)+1)==Seg1[i].y)
	//		//		//  ||(((Points[z].x)-1)==Seg1[i].x&&((Points[z].y)-1)==Seg1[i].y)
	//		//		//  ||(((Points[z].x)+1)==Seg1[i].x&&((Points[z].y)-1)==Seg1[i].y)
	//		//		//  ||(((Points[z].x)-1)==Seg1[i].x&&((Points[z].y)+1)==Seg1[i].y)
	//		//		//  ||(Points[z].x==Seg1[i].x&&((Points[z].y)+1)==Seg1[i].y)
	//		//		//  ||(Points[z].x==Seg1[i].x&&((Points[z].y)-1)==Seg1[i].y)
	//		//		//  ||(Points[z].x==Seg1[i].x&&((Points[z].y)-1)==Seg1[i].y)
	//		//  //        ||(((Points[z].x)-1)==Seg1[i].x&&Points[z].y==Seg1[i].y))
	//		//	 // {

	//		//		//  if ((Seg1.back().x != Points[z].x)||(Seg1.back().y!=Points[z].y))
	//		//		//  {
	//		//	 //     Seg1.push_back(Points[z]);
	//		//		//  flag=true;
	//		//		//  }

	//		//	 // }
	//		//	
	//
	//		//  //}



	//  //  //        if ((Seg1.back().x != Points[z].x)&&(Seg1.back().y!=Points[z].y))
	//
	//		//  //{
	//		//	 //     Segment.push_back(Seg1);
	//		//		//  Seg1.clear();
	//		//		//  Seg1.push_back(cvPoint(Points[z+1].x,Points[z+1].y));
	//		//		//  //Points.erase(Points.begin()+z);
	//		//		//  z--;
	//		//		//  flag=true;
	//		//  //}
	//		//}


	//}
	return 0;
}

vector<vector<CvPoint>> Detection:: GetSegment()
{
	return Segment;
}

vector<CvPoint> Detection::GetPoints()
{
	return Points;
}



